/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.util;
 
/**
 * An implementation of a Linked List ... which would serve as our
 * infinite buffer.
 *
 * @author  : Shrideep Pallickara
 * $Revision$
 * $Date$
 */

public class MessageQueue {
  /** Specifies that the logger Queue is empty */
  protected static final int EMPTY = 0;
  
  /** Specifies that the Queue is neither empty or full
      and can give and accept further data. */
  protected static final int NON_EMPTY_OR_FULL = 1;
  private int state = EMPTY;
  private int length = 0;
  private QueueWidget head;
  private QueueWidget tail;
  
  /**
   * MessageQueue constructor
   */
  public MessageQueue() {
    super();
  }
  /**
   *<a name="addItemToTop()"></a>
   * Adds an Item to the top of the message Queue
   */
  public synchronized void addItemToTop(Object object) {
    if (object == null)
      throw new NullPointerException();
    
    QueueWidget queueWidget = new QueueWidget(object, head, null);
    if (head == null) {
      put(object);
      return;
    }
    head = queueWidget;
    length++;
    updateState();
    this.notify();
  }
  /**
   * clone method comment.
   */
  protected Object clone() {
    return null;
  }
  /**
   * Gets a new Object from the MessageQueue. The item that is returned is the
   * item that is on top of the linked list. If there are no items in the 
   * queue, the queue will be return a NULL. 
   */
  public Object get() {
    if (head == null)
      return null;
    Object object = head.object;
    head = head.prev;
    if (head == null)
      tail = null;
    else
      head.next = null;
    length--;
    //System.gc();
    updateState();
    return object;
  }
  /**
   * 
   * @return int
   */
  public synchronized int getSize() {
    return length;
  }
  /**
   * Returns the current state of the MessageQueue
   */
  protected int getState() {
    return state;
  }
  /**
   * Puts a new Object into the MessageQueue. Will throw a NULL Pointer
   * exception if you are trying to add a null object to the queue. This
   * method needs to be a synchronized method. 
   * @param _object : The object to be inserted into the MessageQueue
   */
  public synchronized void put(Object _object) {
    if (_object == null)
      throw new NullPointerException();
    tail = new QueueWidget(_object, null, tail);
    if (head == null)
      head = tail;
    else
      tail.next.prev = tail;
    length++;
    updateState();
    if (length == 1)
      this.notify();
  }
  /**
   * This method reflects the state of the MessageQueue on the basis of 
   * the length parameter.
   */
  private void updateState() {
    if (length > 0)
      state = NON_EMPTY_OR_FULL;
    else
      state = EMPTY;
  }

  /** The main method, with a built in test case for testing the linked
      list functions.
  */
  public static void main(String[] args) {
    MessageQueue queue = new MessageQueue();
    long startTime, endTime, startTime2;
    double elapsedTime;
    int numOfMessages = 20;
    startTime = System.currentTimeMillis();
    for (int i=0; i < numOfMessages; i++) {
      queue.put(new Integer(i));
    }
    endTime = System.currentTimeMillis();
    elapsedTime = (endTime- startTime)/numOfMessages;
    System.out.println("Mean latency for putting (" + numOfMessages +
		       ") messages is " + elapsedTime + "mSecs");
    queue.addItemToTop(new Integer(20));
    
    startTime = System.currentTimeMillis();
    while (queue.getSize() != 0) {
      startTime2 = System.currentTimeMillis();
      System.out.print(queue.get() + " ");
      endTime = System.currentTimeMillis();
      elapsedTime = (double)(endTime- startTime2);
      System.out.println("Latency for getting a message is " + 
			 elapsedTime + "mSecs");
    }
    System.out.print("\n");
    endTime = System.currentTimeMillis();
    elapsedTime = (double)(endTime- startTime)/(double)numOfMessages;
    System.out.println("Mean latency for Getting " + numOfMessages +
		       " is " + elapsedTime + "mSecs");
  }
}






